package com.cunoraz.continuouscrollable;

import ohos.aafwk.ability.Ability;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.app.Context;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Created by cuneytcarikci on 17/08/2017.
 */
public class ContinuousScrollableImageView extends DirectionalLayout {
    public static final String UP = "up";
    public static final String RIGHT = "right";
    public static final String DOWN = "down";
    public static final String LEFT = "left";
    private static final String DURATION = "duration";
    private static final String IMAGE_SRC = "imageSrc";
    private static final String DIRECTION = "direction";
    private static final String SCALE_TYPE = "scaleType";
    public static final int HORIZONTAL = 0;
    public static final int VERTICAL = 1;

    @Retention(RetentionPolicy.SOURCE)
    @interface Asymptote {
    }

    @Asymptote
    int DEFAULT_ASYMPTOTE = HORIZONTAL;
    public static final String STRETCH = "stretch";
    public static final String ZOOM_START = "zoom_start";
    public static final String ZOOM_CENTER = "zoom_center";
    public static final String ZOOM_END = "zoom_end";
    public static final String CENTER = "center";
    public static final String CLIP_CENTER = "clip_center";
    public static final String INSIDE = "inside";
    private final int DEFAULT_RESOURCE_ID = -1;
    private final int DEFAULT_DURATION = 3000;
    private int DIRECTION_MULTIPLIER = -1;
    private int duration = DEFAULT_DURATION;
    private int resourceId = DEFAULT_RESOURCE_ID;
    private String direction = "left";
    private String scaleType = ZOOM_CENTER;
    private AnimatorValue animator;
    private Image firstImage;
    private Image secondImage;
    private boolean isBuilt = false;
    private AttrUtil attrUtils;

    public ContinuousScrollableImageView(Context context) {
        super(context);
        init(context);
    }

    public ContinuousScrollableImageView(Context context, AttrSet attrs) {
        this(context, attrs, 0);
    }

    public ContinuousScrollableImageView(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, null);
        attrUtils = new AttrUtil(attrs);
        setViewAttributes(context, attrs, defStyleAttr);
        init(context);
    }

    private void setViewAttributes(Context context, AttrSet attrs, int defStyleAttr) {
        duration = attrUtils.getAttrInt(DURATION, 300);
        direction = attrUtils.getAttrString(DIRECTION, "left");
        resourceId = attrUtils.getAttrOther(IMAGE_SRC, -1);
        scaleType = attrUtils.getAttrString(SCALE_TYPE, "zoom_center");
        setDirectionFlags(direction);
    }

    private void setDirectionFlags(String direction) {
        switch (direction) {
            case UP:
                DIRECTION_MULTIPLIER = -1;
                DEFAULT_ASYMPTOTE = VERTICAL;
                break;
            case RIGHT:
                DIRECTION_MULTIPLIER = 1;
                DEFAULT_ASYMPTOTE = HORIZONTAL;
                break;
            case DOWN:
                DIRECTION_MULTIPLIER = 1;
                DEFAULT_ASYMPTOTE = VERTICAL;
                break;
            case LEFT:
                DIRECTION_MULTIPLIER = -1;
                DEFAULT_ASYMPTOTE = HORIZONTAL;
                break;
        }
    }

    /**
     * 初始化页面
     *
     * @param context 上下文
     */
    private void init(Context context) {
        LayoutScatter.getInstance(context).parse(ResourceTable.Layout_continuos_scrollable_imageview_layout, this, true);
        firstImage = (Image) findComponentById(ResourceTable.Id_first_image);
        secondImage = (Image) findComponentById(ResourceTable.Id_second_image);
        build();
    }

    /**
     * Set duration in ms
     *
     * @param duration 持续时间
     */
    public void setDuration(int duration) {
        this.duration = duration;
        isBuilt = false;
    }

    /**
     * 设置滑动方向
     *
     * @param direction 方向
     */
    public void setDirection(String direction) {
        this.direction = direction;
        isBuilt = false;
        setDirectionFlags(direction);
    }

    /**
     * 设置动画图片资源Id
     *
     * @param resourceId 图片资源Id
     */
    public void setResourceId(int resourceId) {
        this.resourceId = resourceId;
        firstImage.setPixelMap(this.resourceId);
        secondImage.setPixelMap(this.resourceId);
    }

    /**
     * set image scale type
     *
     * @param scaleType 方所类型
     */
    public void setScaleType(String scaleType) {
        if (firstImage == null || secondImage == null) {
            throw new NullPointerException();
        }
        Image.ScaleMode type = Image.ScaleMode.CENTER;
        switch (scaleType) {

            case STRETCH:
                type = Image.ScaleMode.STRETCH;
                break;
            case ZOOM_START:
                type = Image.ScaleMode.ZOOM_START;
                break;
            case ZOOM_CENTER:
                type = Image.ScaleMode.ZOOM_CENTER;
                break;
            case ZOOM_END:
                type = Image.ScaleMode.ZOOM_END;
                break;
            case CENTER:
                type = Image.ScaleMode.CENTER;
                break;
            case CLIP_CENTER:
                type = Image.ScaleMode.CLIP_CENTER;
                break;
            case INSIDE:
                type = Image.ScaleMode.INSIDE;
                break;
        }
        this.scaleType = scaleType;
        firstImage.setScaleMode(type);
        secondImage.setScaleMode(type);
    }

    private void build() {
        if (isBuilt) {
            return;
        }
        isBuilt = true;
        setImages();
        if (animator != null) {
            animator.release();
        }
        animator = new AnimatorValue();
        animator.setLoopedCount(Integer.MAX_VALUE);
        animator.setCurveType(Animator.CurveType.LINEAR);
        animator.setDuration(duration);
        switch (DEFAULT_ASYMPTOTE) {
            case HORIZONTAL:
                animator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                    @Override
                    public void onUpdate(AnimatorValue animatorValue, float value) {
                        float width = DIRECTION_MULTIPLIER * (firstImage.getWidth());
                        float translationX = width * value;
                        firstImage.setTranslationX(translationX);
                        secondImage.setTranslationX(translationX - width);
                    }
                });
                break;
            case VERTICAL:
                animator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
                    @Override
                    public void onUpdate(AnimatorValue animatorValue, float value) {
                        float height = DIRECTION_MULTIPLIER * (firstImage.getHeight());
                        float translationY = height * value;
                        firstImage.setTranslationY(translationY);
                        secondImage.setTranslationY(translationY - height);
                    }
                });
                break;
        }
        animator.start();
    }

    private void setImages() {
        if (resourceId == -1) {
            return;
        }
        firstImage.setPixelMap(resourceId);
        secondImage.setPixelMap(resourceId);
        setScaleType(scaleType);
    }

    public static final class Builder {
        private ContinuousScrollableImageView scrollableImageView;
        private Context context;

        public Builder(Ability activity) {
            context = activity;
            scrollableImageView = new ContinuousScrollableImageView(activity);
        }

        public Builder setDuration(int duration) {
            scrollableImageView.setDuration(duration);
            return this;
        }

        public Builder setResourceId(int resourceId) {
            scrollableImageView.setResourceId(resourceId);
            return this;
        }

        public Builder setDirection(String direction) {
            scrollableImageView.setDirection(direction);
            return this;
        }

        public Builder setScaleType(String scaleType) {
            scrollableImageView.setScaleType(scaleType);
            return this;
        }

        public ContinuousScrollableImageView build() {
            scrollableImageView.init(context);
            return scrollableImageView;
        }
    }
}
